package org.apache.james.imap.server;

import javax.mail.Flags;

import org.apache.james.api.imap.message.MessageFlags;
import org.apache.james.imapserver.ImapConstants;
import org.apache.james.imapserver.ImapResponse;
import org.apache.james.imapserver.commands.ImapCommand;
import org.apache.mina.common.IoSession;

public class SimpleImapResponse implements ImapResponse {

    final static String OK = "OK";
    final static String NO = "NO";
    final static String BAD = "BAD";
    final static String BYE = "BYE";
    final static char UNTAGGED = '*';

	private final static char SP = ' ';

	StringBuilder buffer;
    
	private String tag = ImapConstants.UNTAGGED;
	
	IoSession output;

	public SimpleImapResponse(IoSession output) {
		this.buffer = new StringBuilder();
		this.output = output;
	}

	public SimpleImapResponse() {
		this.buffer = new StringBuilder();
	}

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#setTag(java.lang.String)
	 */
    public void setTag( String tag )
    {
        this.tag = tag;
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandComplete(org.apache.james.imapserver.commands.ImapCommand)
	 */
    public void commandComplete( ImapCommand command )
    {
        commandComplete( command, null );
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandComplete(org.apache.james.imapserver.commands.ImapCommand, java.lang.String)
	 */
    public void commandComplete( ImapCommand command, String responseCode )
    {
        tag();
        message( OK );
        responseCode( responseCode );
        commandName( command );
        message( "completed." );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandFailed(org.apache.james.imapserver.commands.ImapCommand, java.lang.String)
	 */
    public void commandFailed( ImapCommand command, String reason )
    {
        commandFailed( command, null, reason );
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandFailed(org.apache.james.imapserver.commands.ImapCommand, java.lang.String, java.lang.String)
	 */
    public void commandFailed( ImapCommand command,
                               String responseCode,
                               String reason )
    {
        tag();
        message( NO );
        responseCode( responseCode );
        commandName( command );
        message( "failed." );
        message( reason );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandError(java.lang.String)
	 */
    public void commandError( String message )
    {
        tag();
        message( BAD );
        message( message );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#badResponse(java.lang.String)
	 */
    public void badResponse( String message )
    {
        untagged();
        message( BAD );
        message( message );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#okResponse(java.lang.String, java.lang.String)
	 */
    public void okResponse( String responseCode, String message )
    {
        untagged();
        message( OK );
        responseCode( responseCode );
        message( message );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#flagsResponse(javax.mail.Flags)
	 */
    public void flagsResponse( Flags flags )
    {
        untagged();
        message( "FLAGS" );
        message( MessageFlags.format(flags) );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#existsResponse(int)
	 */
    public void existsResponse( int count )
    {
        untagged();
        message( count );
        message( "EXISTS" );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#recentResponse(int)
	 */
    public void recentResponse( int count )
    {
        untagged();
        message( count );
        message( "RECENT" );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#expungeResponse(int)
	 */
    public void expungeResponse( int msn )
    {
        untagged();
        message( msn );
        message( "EXPUNGE" );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#fetchResponse(int, java.lang.String)
	 */
    public void fetchResponse( int msn, String msgData )
    {
        untagged();
        message( msn );
        message( "FETCH" );
        message( "(" + msgData + ")" );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#commandResponse(org.apache.james.imapserver.commands.ImapCommand, java.lang.String)
	 */
    public void commandResponse( ImapCommand command, String message )
    {
        untagged();
        commandName( command );
        message( message );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#taggedResponse(java.lang.String)
	 */
    public void taggedResponse( String message )
    {
        tag();
        message( message );
        end();
    }

    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#untaggedResponse(java.lang.String)
	 */
    public void untaggedResponse( String message )
    {
        untagged();
        message( message );
        end();
    }
    
    /* (non-Javadoc)
	 * @see org.apache.james.imapserver.ImapResponse#byeResponse(java.lang.String)
	 */
    public void byeResponse( String message ) {
        untaggedResponse(BYE + SP + message);
    }

	public void permanentFlagsResponse(Flags flags) {
        untagged();
        message(OK);
        responseCode("PERMANENTFLAGS " + MessageFlags.format(flags));
        end();
	}
	
	

	
	
    private final void untagged()
    {
        buffer.append( UNTAGGED );
    }

    private final void tag()
    {
    	buffer.append( tag );
    }

    private final void commandName( ImapCommand command )
    {
        buffer.append( SP ).append( command.getName());
    }

    private final void message( String message )
    {
        if ( message != null ) {
            buffer.append( SP ).append( message );
        }
    }

    private final void message( int number )
    {
        buffer.append( SP ).append( number );
    }

    private final void responseCode( String responseCode )
    {
        if ( responseCode != null ) {
            buffer.append( " [" ).append( responseCode ).append( "]" );
        }
    }

    protected void end()
    {
    	output.write(buffer.toString());
    	buffer.setLength(0);
    }

}
